/*****************************************************************************/
/*!	\file		PIS10Handlers.c
 *	\brief		C Source code file for the YX-PIS Example
 *	\par		Dalian Yunxing Tech Co., Ltd.
 *
 *				Dalian, China
 *				Phone   : +86 (411) 8825 4852
 *				Email   : yx@yunxing.tech
 */
/*****************************************************************************/

#include <stdio.h>
#include <string.h>
#include "IEC61850Functions.h"
#include "IEC61850API.h"
#include "UserInput.h"
#include "PrintView.h"
#include "LocalData.h"
#include "PIS10CreateServerClient.h"


IEC61850_ErrorCode GetConnectionsList()
{
	IEC61850_ErrorCode result = S_OK;
	IEC61850 iec61850 = GetMyServerClient();
	ConnectionList connectionList = { 0 };

	result = IEC61850_GetConnectionsList(iec61850, &connectionList);
	if (result == S_OK) {
		printf("\nNum of connection: (%u)\n", connectionList.length);
		if (connectionList.length > 0) {
			U32 index = 0;
			char strError[SIZE_OF_ERROR_STRING] = { 0 };	/* Set the Error String to NONE */
			snprintf(strError, SIZE_OF_ERROR_STRING, "Get connected server list success.");	/* Set error message to show success */
			SetErrorString(strError, SIZE_OF_ERROR_STRING);

			/* Print the list */
			printf("\t[Index]\t[IP]\t\t[Status]\t[IED Name]\n");
			for (index = 0; index < connectionList.length; index++) {
				printf("\t%u\t%s\t%s\t%s\n",
					connectionList.connections[index].AAIndex,
					connectionList.connections[index].IPAddress,
					connectionList.connections[index].bConnectionState ? "Connected" : "Disconnected",
					connectionList.connections[index].iedName);
			}
		}
		/* Wait for user */
		printf("\nPress enter to continue.");
		getchar();
	} else {
		/* If the function failed alert the user */
		char strError[SIZE_OF_ERROR_STRING] = { 0 };
		snprintf(strError, SIZE_OF_ERROR_STRING, "Get connected IED list failed: %i: %s\n", result, IEC61850_ErrorString(result) == NULL ? "Error" : IEC61850_ErrorString(result));
		SetErrorString(strError, SIZE_OF_ERROR_STRING);
	}
	return result;
}

IEC61850_ErrorCode UpdateMMXUPhsAMagi(S32 newValue)
{
	IEC61850_ErrorCode result = S_OK;

	IEC61850_DataAttributeID daid = { 3, 0, 0, 0, 0 };
	IEC61850_DataAttributeData daData = { 0 };

	IEC61850 iec61850 = GetMyServerClient();

	/* Setup the Data Attribute Data Struct */
	daData.bitLength = sizeof(S32) * 8;	// set the size of the data in bits
	daData.type = IEC61850_DATATYPE_INT32;	// set the type of the data
	daData.pvData = &newValue;	// Set a pointer to the data

	/* Perform the Update */
	result = IEC61850_Update(iec61850, &daid, &daData, 1);	// count of 1 as only 1 element is being updated

	if (result == S_OK) {
		/* Set the Error String to NONE */
		char strError[SIZE_OF_ERROR_STRING] = { 0 };
		SetErrorString(strError, SIZE_OF_ERROR_STRING);

		/* If the Update Succeeded Update the local value for the gui*/
		SetMMXUPhsAMagi(newValue);
	} else {
		/* If the Update failed alert the user */
		char strError[SIZE_OF_ERROR_STRING] = { 0 };
		snprintf(strError, SIZE_OF_ERROR_STRING, "UpdateMMXUPhsAMagi Update failed:(%i) %s\n", result, IEC61850_ErrorString(result));
		SetErrorString(strError, SIZE_OF_ERROR_STRING);
	}

	return result;
}

IEC61850_ErrorCode UpdateMMXUPhsBMagi(S32 newValue)
{
	IEC61850_ErrorCode result = S_OK;

	IEC61850_DataAttributeID daid = { 4, 0, 0, 0, 0 };
	IEC61850_DataAttributeData daData = { 0 };

	IEC61850 iec61850 = GetMyServerClient();

	/* Setup the Data Attribute Data Struct */
	daData.bitLength = sizeof(S32) * 8;	// set the size of the data in bits
	daData.type = IEC61850_DATATYPE_INT32;	// set the type of the data
	daData.pvData = &newValue;	// set a pointer to the data

	/* Perform the Update */
	result = IEC61850_Update(iec61850, &daid, &daData, 1);	// count of 1 as only 1 element is being updated

	if (result == S_OK) {
		/* Set the Error String to NONE */
		char strError[SIZE_OF_ERROR_STRING] = { 0 };
		SetErrorString(strError, SIZE_OF_ERROR_STRING);

		/* If the Update Succeeded Update the local value for the gui*/
		SetMMXUPhsBMagi(newValue);
	} else {
		/* If the Update failed alert the user */
		char strError[SIZE_OF_ERROR_STRING] = { 0 };
		snprintf(strError, SIZE_OF_ERROR_STRING, "MMXUPhsBMagi Update failed:(%i) %s\n", result, IEC61850_ErrorString(result));
		SetErrorString(strError, SIZE_OF_ERROR_STRING);
	}

	return result;
}

IEC61850_ErrorCode UpdateMMXUPhsCMagi(S32 newValue)
{
	IEC61850_ErrorCode result = S_OK;

	IEC61850_DataAttributeID daid = { 5, 0, 0, 0, 0 };
	IEC61850_DataAttributeData daData = { 0 };

	IEC61850 iec61850 = GetMyServerClient();

	/* Setup the Data Attribute Data Struct */
	daData.bitLength = sizeof(S32) * 8;	// set the size of the data in bits
	daData.type = IEC61850_DATATYPE_INT32;	// set the type of the data
	daData.pvData = &newValue;	// set a pointer to the data

	result = IEC61850_Update(iec61850, &daid, &daData, 1);	// count of 1 as only 1 element is being updated

	if (result == S_OK) {
		/* Set the Error String to NONE */
		char strError[SIZE_OF_ERROR_STRING] = { 0 };
		SetErrorString(strError, SIZE_OF_ERROR_STRING);

		/* If the Update Succeeded Update the local value for the gui*/
		SetMMXUPhsCMagi(newValue);
	} else {
		/* If the Update failed alert the user */
		char strError[SIZE_OF_ERROR_STRING] = { 0 };
		snprintf(strError, SIZE_OF_ERROR_STRING, "MMXUPhsCMagi Update failed:(%i) %s\n", result, IEC61850_ErrorString(result));
		SetErrorString(strError, SIZE_OF_ERROR_STRING);
	}

	return result;
}

IEC61850_ErrorCode UpdateTTNSTnsSv1Magf(Float32 newValue)
{
	IEC61850_ErrorCode result = S_OK;

	IEC61850_DataAttributeID daid = { 7, 0, 0, 0, 0 };
	IEC61850_DataAttributeData daData = { 0 };

	IEC61850 iec61850 = GetMyServerClient();

	/* Setup the Data Attribute Data Struct */
	daData.bitLength = sizeof(Float32) * 8;	// set the size of the data in bits
	daData.type = IEC61850_DATATYPE_FLOAT32;	// set the type of the data
	daData.pvData = &newValue;	// set a pointer to the data

	result = IEC61850_Update(iec61850, &daid, &daData, 1);	// count of 1 as only 1 element is being updated

	if (result == S_OK) {
		/* Set the Error String to NONE */
		char strError[SIZE_OF_ERROR_STRING] = { 0 };
		SetErrorString(strError, SIZE_OF_ERROR_STRING);

		/* If the Update Succeeded Update the local value for the gui*/
		SetTTNSTnsSv1Magf(newValue);
	} else {
		/* If the Update failed alert the user */
		char strError[SIZE_OF_ERROR_STRING] = { 0 };
		snprintf(strError, SIZE_OF_ERROR_STRING, "UpdateTTNSTnsSv1Magf Update failed:(%i) %s\n", result, IEC61850_ErrorString(result));
		SetErrorString(strError, SIZE_OF_ERROR_STRING);
	}

	return result;
}

IEC61850_ErrorCode UpdateTTNSTnsSv2Magf(Float32 newValue)
{
	IEC61850_ErrorCode result = S_OK;

	IEC61850_DataAttributeID daid = { 7, 0, 0, 0, 1 };
	IEC61850_DataAttributeData daData = { 0 };

	IEC61850 iec61850 = GetMyServerClient();

	/* Setup the Data Attribute Data Struct */
	daData.bitLength = sizeof(Float32) * 8;	// set the size of the data in bits
	daData.type = IEC61850_DATATYPE_FLOAT32;	// set the type of the data
	daData.pvData = &newValue;	// set a pointer to the data

	result = IEC61850_Update(iec61850, &daid, &daData, 1);	// count of 1 as only 1 element is being updated

	if (result == S_OK) {
		/* Set the Error String to NONE */
		char strError[SIZE_OF_ERROR_STRING] = { 0 };
		SetErrorString(strError, SIZE_OF_ERROR_STRING);

		/* If the Update Succeeded Update the local value for the gui*/
		SetTTNSTnsSv2Magf(newValue);
	} else {
		/* If the Update failed alert the user */
		char strError[SIZE_OF_ERROR_STRING] = { 0 };
		snprintf(strError, SIZE_OF_ERROR_STRING, "UpdateTTNSTnsSv2Magf Update failed:(%i) %s\n", result, IEC61850_ErrorString(result));
		SetErrorString(strError, SIZE_OF_ERROR_STRING);
	}

	return result;
}

IEC61850_ErrorCode UpdateTTNSTnsSv3Magf(Float32 newValue)
{
	IEC61850_ErrorCode result = S_OK;

	IEC61850_DataAttributeID daid = { 7, 0, 0, 0, 2 };
	IEC61850_DataAttributeData daData = { 0 };

	IEC61850 iec61850 = GetMyServerClient();

	/* Setup the Data Attribute Data Struct */
	daData.bitLength = sizeof(Float32) * 8;	// set the size of the data in bits
	daData.type = IEC61850_DATATYPE_FLOAT32;	// set the type of the data
	daData.pvData = &newValue;	// set a pointer to the data

	result = IEC61850_Update(iec61850, &daid, &daData, 1);	// count of 1 as only 1 element is being updated

	if (result == S_OK) {
		/* Set the Error String to NONE */
		char strError[SIZE_OF_ERROR_STRING] = { 0 };
		SetErrorString(strError, SIZE_OF_ERROR_STRING);

		/* If the Update Succeeded Update the local value for the gui*/
		SetTTNSTnsSv3Magf(newValue);
	} else {
		/* If the Update failed alert the user */
		char strError[SIZE_OF_ERROR_STRING] = { 0 };
		snprintf(strError, SIZE_OF_ERROR_STRING, "UpdateTTNSTnsSv3Magf Update failed:(%i) %s\n", result, IEC61850_ErrorString(result));
		SetErrorString(strError, SIZE_OF_ERROR_STRING);
	}

	return result;
}

IEC61850_ErrorCode UpdatePDIFCrvPts(CrvPts newValue, S8 index)
{
	IEC61850_ErrorCode result = S_OK;

	IEC61850_DataAttributeID daid = { 6, 0, 0, 0, 0 };
	IEC61850_DataAttributeData daData = { 0 };
	IEC61850_DataAttributeData xyValDAData[NUM_CRVPTS_STRUCT_ELEMENTS] = { 0 };
	IEC61850 iec61850 = GetMyServerClient();

	/* Setup the Data Attribute Data Struct */
	daData.arrayIndex = index;	// set the index to be updated
	daData.bitLength = NUM_CRVPTS_STRUCT_ELEMENTS;	// set the size of the Array being passed in. 2 elements in this case (xVal and yVal)
	daData.type = IEC61850_DATATYPE_ARRAY;	// set the type of the data
	daData.pvData = xyValDAData;	// set a pointer to the data

	/* Setup the xVal */
	xyValDAData[0].type = IEC61850_DATATYPE_FLOAT32;
	xyValDAData[0].bitLength = sizeof(Float32) * 8;
	xyValDAData[0].pvData = &(newValue.xVal);

	/* Setup the yVal */
	xyValDAData[1].type = IEC61850_DATATYPE_FLOAT32;
	xyValDAData[1].bitLength = sizeof(Float32) * 8;
	xyValDAData[1].pvData = &(newValue.yVal);

	result = IEC61850_Update(iec61850, &daid, &daData, 1);

	if (result == S_OK) {
		/* Set the Error String to NONE */
		char strError[SIZE_OF_ERROR_STRING] = { 0 };
		SetErrorString(strError, SIZE_OF_ERROR_STRING);

		/* If the Update Succeeded Update the local value for the gui*/
		SetPDIFCrvPts(index, newValue);
	} else {
		/* If the Update failed alert the user */
		char strError[SIZE_OF_ERROR_STRING] = { 0 };
		snprintf(strError, SIZE_OF_ERROR_STRING, "PDIFCrvPtsYVal[%d] Update failed:(%i) %s\n", index, result, IEC61850_ErrorString(result));
		SetErrorString(strError, SIZE_OF_ERROR_STRING);
	}

	return result;
}

void ControlOperateDemo()
{
	char continueMainLoop = 'y';
	char usrCommand = 0;
	Boolean boolVal = FALSE;
	IEC61850_ErrorCode IEC61850Error = S_OK;
	do {
		PrintControlMenuView();

		usrCommand = GetCommIndexFromUser();

		switch (usrCommand) {
		case 0:
			continueMainLoop = 'n';
			break;
		case 1:
			/* Get a value from user */
			boolVal = GetBooleanFromUser();
			/* Do the Operate with the value*/
			OperateGGIO(boolVal, 1);
			break;
		case 2:
			/* Get a value from user */
			boolVal = GetBooleanFromUser();
			IEC61850Error = SelectGGIO();
			/* Do the Operate with the value*/
			OperateGGIO(boolVal, 2);
			break;
		case 3:
			/* Get a value from user */
			boolVal = GetBooleanFromUser();
			/* Do the Operate with the value*/
			OperateGGIO(boolVal, 3);
			break;
		case 4:
			/* Get a value from user */
			boolVal = GetBooleanFromUser();
			SelectGGIOWithVal(boolVal);
			/* Do the Operate with the value*/
			OperateGGIO(boolVal, 4);
			break;
		case 5:
			boolVal = GetBooleanFromUser();
			/* CSWI is SBO with enhanced Security so we need to do Select first with the value*/
			IEC61850Error = SelectCSWI(boolVal);
			if (IEC61850Error == S_OK) {
				/* Do the Operate with the value*/
				OperateCSWI(boolVal);
			}
			break;
		default:
			break;
		}

	} while (continueMainLoop == 'y');
}

void DataAccess()
{
	char continueMainLoop = 'y';
	char usrCommand = 0;
	do {
		PrintDataAccessMenuView();

		usrCommand = GetCommIndexFromUser();

		switch (usrCommand) {
		case 0:
			continueMainLoop = 'n';
			break;
		case 1:
			GetServerDir();
			break;
		case 2:
			GetLDDir();
			break;
		case 3:
			GetLNDir();
			break;
		case 4:
			GetAllDataValues();
			break;
		case 5:
			GetAllCBValues();
			break;
		case 6:
			GetDataValues();
			break;
		case 7:
			SetDataValues();
			break;
		case 8:
			GetDataDirectory();
			break;
		case 9:
			GetDataDefinition();
			break;
		case 10:
			GetDataSetValues();
			break;
		case 11:
			SetDataSetValues();
			break;
		case 12:
			CreateDataSet();
			break;
		case 13:
			DeleteDataSet();
			break;
		case 14:
			GetDataSetDirectory();
			break;
		default:
			break;
		}

	} while (continueMainLoop == 'y');
}

void ReportOperate()
{
	char continueMainLoop = 'y';
	char usrCommand = 0;
	do {
		PrintReportMenuView();

		usrCommand = GetCommIndexFromUser();

		switch (usrCommand) {
		case 0:
			continueMainLoop = 'n';
			break;
		case 1:
			GetBufferedReportControlBlockValues();
			break;
		case 2:
			SetBufferedReportControlBlockValues();
			break;
		case 3:
			GetUnbufferedReportControlBlockValues();
			break;
		case 4:
			SetUnbufferedReportControlBlockValues();
			break;
		default:
			break;
		}
	} while (continueMainLoop == 'y');
}

void LogOperate()
{
	char continueMainLoop = 'y';
	S32 usrCommand = 0;
	do {
		PrintLogMenuView();
		usrCommand = GetCommIndexFromUser();
		switch (usrCommand) {
		case 0:
			continueMainLoop = 'n';
			break;
		case 1:
			QueryLogByTime();
			break;
		case 2:
			QueryLogAfter();
			break;
		case 3:
			GetLogStatusValues();
			break;
		default:
			break;
		}
	} while (continueMainLoop == 'y');
}

void SettingGroupOperate()
{
	char continueMainLoop = 'y';
	char usrCommand = 0;
	do {
		PrintSettingGroupMenuView();

		usrCommand = GetCommIndexFromUser();

		switch (usrCommand) {
		case 0:
			continueMainLoop = 'n';
			break;
		case 1:
			GetEditSGValue();
			// continueMainLoop = 'n';
			break;
		case 2:
			SelectActiveSG();
			break;
		case 3:
			SelectEditSG();
			break;
		case 4:
			SetEditSGValue();
			break;
		case 5:
			ConfirmEditSGValues();
			break;
		case 6:
			GetSGCBValues();
			break;
		default:
			break;
		}
	} while (continueMainLoop == 'y');
}

void FileOperate()
{
	char continueMainLoop = 'y';
	char usrCommand = 0;
	do {
		PrintFileMenuView();

		usrCommand = GetCommIndexFromUser();

		switch (usrCommand) {
		case 0:
			continueMainLoop = 'n';
			break;
		case 1:
			MMSGetFile();
			break;
		case 2:
			MMSSetFile();
			break;
		case 3:
			MMSDeleteFile();
			break;
		case 4:
			MMSGetFileAttributeValues();
			break;
		default:
			break;
		}

	} while (continueMainLoop == 'y');
}

void MMSReadOrWrite()
{
	char continueMainLoop = 'y';
	char usrCommand = 0;
	do {
		printf("1) Read\n");
		printf("2) Write\n");
		printf("0) Return to main menu\n");

		usrCommand = GetCommIndexFromUser();

		switch (usrCommand) {
		case 0:
			continueMainLoop = 'n';
			break;
		case 1:
			MMS_Read();
			break;
		case 2:
			MMS_Write();
			break;
		default:
			break;
		}
	} while (continueMainLoop == 'y');
}

IEC61850_ErrorCode SelectCSWI(Boolean ctlVal)
{
	IEC61850_ErrorCode result = S_OK;

	IEC61850_DataAttributeID daid = { 1, 0, 0, 0, 0 };
	IEC61850_DataAttributeData daData = { 0 };
	IEC61850_ControlParameters ctlParam = { 0 };

	IEC61850 iec61850 = GetMyServerClient();

	/* Setup the Data Attribute Data Struct */
	daData.bitLength = IEC61850_BOOLEAN_BITSIZE;	// set the size of the data in bits
	daData.type = IEC61850_DATATYPE_BOOLEAN;	// set the type of the data
	daData.pvData = &ctlVal;	// set a pointer to the data

	/* Perform the Select */
	result = IEC61850_ControlSelect(iec61850, &daid, &daData, &ctlParam);

	/* If the Select failed alert the user */
	if (result != S_OK) {
		char strError[SIZE_OF_ERROR_STRING] = { 0 };
		snprintf(strError, SIZE_OF_ERROR_STRING, "CSWI Select failed:(%i) %s\n", result, IEC61850_ErrorString(result));
		SetErrorString(strError, SIZE_OF_ERROR_STRING);
	} else {
		/* Set the Error String to NONE */
		char strError[SIZE_OF_ERROR_STRING] = { 0 };
		SetErrorString(strError, SIZE_OF_ERROR_STRING);
	}

	return result;
}

IEC61850_ErrorCode OperateCSWI(Boolean ctlVal)
{
	IEC61850_ErrorCode result = S_OK;

	IEC61850_DataAttributeID daid = { 1, 0, 0, 0, 0 };
	IEC61850_DataAttributeData daData = { 0 };
	IEC61850_ControlParameters ctlParam = { 0 };

	IEC61850 iec61850 = GetMyServerClient();

	/* Setup the Data Attribute Data Struct */
	daData.bitLength = IEC61850_BOOLEAN_BITSIZE;	// set the size of the data in bits
	daData.type = IEC61850_DATATYPE_BOOLEAN;	// set the type of the data
	daData.pvData = &ctlVal;	// set a pointer to the data

	/* Perform the Operate */
	result = IEC61850_ControlOperate(iec61850, &daid, &daData, &ctlParam);

	if (result == S_OK) {
		/* Set the Error String to NONE */
		char strError[SIZE_OF_ERROR_STRING] = { 0 };
		SetErrorString(strError, SIZE_OF_ERROR_STRING);
	} else {
		/* If the Operate failed alert the user */
		char strError[SIZE_OF_ERROR_STRING] = { 0 };
		snprintf(strError, SIZE_OF_ERROR_STRING, "CSWI Operate failed:(%i) %s\n", result, IEC61850_ErrorString(result));
		SetErrorString(strError, SIZE_OF_ERROR_STRING);
	}

	return result;
}

IEC61850_ErrorCode SelectGGIO()
{
	IEC61850_ErrorCode result = S_OK;

	IEC61850_DataAttributeID daid = { 2, 0, 0, 0, 2 };
	IEC61850_ControlParameters ctlParam = { 0 };

	IEC61850 iec61850 = GetMyServerClient();

	/* Perform the Select */
	// Select by DAID
	result = IEC61850_ControlSelect(iec61850, &daid, NULL, &ctlParam);

	// // Select by sAddr
	// result = IEC61850_ControlSelectWithShortAddr(iec61850, "stVal@2.0.0.0.2", NULL, &ctlParam);

	/* If the Select failed alert the user */
	if (result != S_OK) {
		char strError[SIZE_OF_ERROR_STRING] = { 0 };
		snprintf(strError, SIZE_OF_ERROR_STRING, "GGIO Select failed:(%i) %s\n", result, IEC61850_ErrorString(result));
		SetErrorString(strError, SIZE_OF_ERROR_STRING);
	} else {
		/* Set the Error String to NONE */
		char strError[SIZE_OF_ERROR_STRING] = { 0 };
		SetErrorString(strError, SIZE_OF_ERROR_STRING);
	}

	return result;
}

IEC61850_ErrorCode SelectGGIOWithVal(Boolean ctlVal)
{
	IEC61850_ErrorCode result = S_OK;

	IEC61850_DataAttributeID daid = { 2, 0, 0, 0, 4 };
	IEC61850_DataAttributeData daData = { 0 };
	IEC61850_ControlParameters ctlParam = { 0 };

	IEC61850 iec61850 = GetMyServerClient();

	/* Setup the Data Attribute Data Struct */
	daData.bitLength = IEC61850_BOOLEAN_BITSIZE;	// set the size of the data in bits
	daData.type = IEC61850_DATATYPE_BOOLEAN;	// set the type of the data
	daData.pvData = &ctlVal;	// set a pointer to the data

	/* Perform the Select */
	// Select(SelectWithValue) by DAID
	result = IEC61850_ControlSelect(iec61850, &daid, &daData, &ctlParam);

	// // Select(SelectWithValue) by sAddr
	// result = IEC61850_ControlSelectWithShortAddr(iec61850, "stVal@2.0.0.0.4", &daData, &ctlParam);

	/* If the Select failed alert the user */
	if (result != S_OK) {
		char strError[SIZE_OF_ERROR_STRING] = { 0 };
		snprintf(strError, SIZE_OF_ERROR_STRING, "GGIO Select failed:(%i) %s\n", result, IEC61850_ErrorString(result));
		SetErrorString(strError, SIZE_OF_ERROR_STRING);
	} else {
		/* Set the Error String to NONE */
		char strError[SIZE_OF_ERROR_STRING] = { 0 };
		SetErrorString(strError, SIZE_OF_ERROR_STRING);
	}

	return result;
}

IEC61850_ErrorCode OperateGGIO(Boolean ctlVal, int index)
{
	IEC61850_ErrorCode result = S_OK;

	IEC61850_DataAttributeID daid = { 2, 0, 0, 0, index };
	IEC61850_DataAttributeData daData = { 0 };
	IEC61850_ControlParameters ctlParam = { 0 };

	IEC61850 iec61850 = GetMyServerClient();

	/* Setup the Data Attribute Data Struct */
	daData.bitLength = IEC61850_BOOLEAN_BITSIZE;	// set the size of the data in bits
	daData.type = IEC61850_DATATYPE_BOOLEAN;	// set the type of the data
	daData.pvData = &ctlVal;	// set a pointer to the data

	/* Perform the Operate */
	// Operate by DAID
	result = IEC61850_ControlOperate(iec61850, &daid, &daData, &ctlParam);

	// // Operate by sAddr
	// if (index == 1) {
	// 	result = IEC61850_ControlOperateWithShortAddr(iec61850, "stVal@2.0.0.0.1", &daData, &ctlParam);
	// } else if (index == 2) {
	// 	result = IEC61850_ControlOperateWithShortAddr(iec61850, "stVal@2.0.0.0.2", &daData, &ctlParam);
	// } else if (index == 3) {
	// 	result = IEC61850_ControlOperateWithShortAddr(iec61850, "stVal@2.0.0.0.3", &daData, &ctlParam);
	// } else if (index == 4) {
	// 	result = IEC61850_ControlOperateWithShortAddr(iec61850, "stVal@2.0.0.0.4", &daData, &ctlParam);
	// }

	if (result == S_OK) {
		/* Set the Error String to NONE */
		char strError[SIZE_OF_ERROR_STRING] = { 0 };
		SetErrorString(strError, SIZE_OF_ERROR_STRING);
		/* If the Operate Succeeded Update the local value for the gui*/
	} else {
		/* If the Operate failed alert the user */
		char strError[SIZE_OF_ERROR_STRING] = { 0 };
		snprintf(strError, SIZE_OF_ERROR_STRING, "GGIO Operate failed:(%i) %s\n", result, IEC61850_ErrorString(result));
		SetErrorString(strError, SIZE_OF_ERROR_STRING);
	}

	return result;
}

IEC61850_ErrorCode GetServerDir()
{
	IEC61850_ErrorCode result = S_OK;
	IEC61850 iec61850 = GetMyServerClient();
	unsigned int serverIndex = 0;
	GetServerDirectory_Request request = { 0 };
	GetServerDirectory_Response response = { 0 };

	result = IEC61850_GetServerDirectory(iec61850, serverIndex, &request, &response);
	if (result == S_OK) {
		PrintGetServerDirectoryResponse(&response);
	} else {
		printf("result:[%d]\n", result);
	}
	FreeGetServerDirectory_Response(&response);

	return result;
}

IEC61850_ErrorCode GetLDDir()
{
	IEC61850_ErrorCode result = S_OK;
	IEC61850 iec61850 = GetMyServerClient();
	unsigned int serverIndex = 0;
	GetLogicalDeviceDirectory_Request request = { 0 };
	GetLogicalDeviceDirectory_Response response = { 0 };
	request.ldName = "ServerIEDExample";

	result = IEC61850_GetLogicalDeviceDirectory(iec61850, serverIndex, &request, &response);
	if (result == S_OK) {
		PrintGetLogicalDeviceDirectoryResponse(&response);
	} else {
		printf("result:[%d]\n", result);
	}
	FreeGetLogicalDeviceDirectory_Response(&response);
	return result;
}

IEC61850_ErrorCode GetLNDir()
{
	IEC61850_ErrorCode result = S_OK;
	IEC61850 iec61850 = GetMyServerClient();
	unsigned int serverIndex = 0;
	GetLogicalNodeDirectory_Request  request = { 0 };
	GetLogicalNodeDirectory_Response response = { 0 };
	unsigned int lnIndex = 0;
	struct StringList* lnRefList = StringListMalloc();
	U32 acsiClass = 0;

	StringListAdd(lnRefList, "ServerIEDExample/LLN0");
	StringListAdd(lnRefList, "ServerIEDExample/CSWI0");
	StringListAdd(lnRefList, "ServerIEDExample/GGIO0");
	StringListAdd(lnRefList, "ServerIEDExample/MMXU0");
	StringListAdd(lnRefList, "ServerIEDExample/PDIF0");
	StringListAdd(lnRefList, "ServerIEDExample/IARC0");

	if (lnRefList->length <= 0) {
		return IEC61850_ERROR_NO_MEMORY;
	}

	printf("LN Reference List:\n");
	PrintStringList(lnRefList);
	printf("Please select LN ref:\n");

	lnIndex = GetIndexFromUser();

	printf("Please select the ACSIClass from:\n");
	printf("  1. DataObject\n");
	printf("  2. DATA-SET\n");
	printf("  3. BRCB\n");
	printf("  4. URCB\n");
	printf("  5. LCB\n");
	printf("  6. LOG\n");
	printf("  7. SGCB\n");
	printf("  8. GoCB\n");
	printf(" 10. MSVCB\n");
	acsiClass = GetIndexFromUser();
	printf("\n");

	request.reference = "";
	if (lnIndex >= 1 && lnIndex <= lnRefList->length) {
		request.reference = lnRefList->list[lnIndex - 1];
	}
	request.acsiClass = (enum IEC61850_ACSIClass)acsiClass;
	result = IEC61850_GetLogicalNodeDirectory(iec61850, serverIndex, &request, &response);
	if (result == S_OK) {
		PrintGetLogicalNodeDirectoryResponse(&response);
	} else {
		printf("result:[%d]\n", result);
	}
	FreeGetLogicalNodeDirectory_Response(&response);
	FreeStringList(lnRefList);
	return result;
}

IEC61850_ErrorCode GetAllDataValues()
{
	IEC61850_ErrorCode result = S_OK;
	IEC61850 iec61850 = GetMyServerClient();
	unsigned int serverIndex = 0;
	GetAllData_Request request = { 0 };
	GetAllDataValues_Response response = { 0 };
	int i = 0;
	unsigned int lnIndex = 0;
	unsigned int fcIndex = 0;
	char FC[13][3] = { "ST","MX","SP","SV","CF","DC","SG","SE","SR","OR","BL","EX","XX" };
	struct StringList* lnRefList = StringListMalloc();

	StringListAdd(lnRefList, "ServerIEDExample/LLN0");
	StringListAdd(lnRefList, "ServerIEDExample/CSWI0");
	StringListAdd(lnRefList, "ServerIEDExample/GGIO0");
	StringListAdd(lnRefList, "ServerIEDExample/MMXU0");
	StringListAdd(lnRefList, "ServerIEDExample/PDIF0");
	StringListAdd(lnRefList, "ServerIEDExample/IARC0");
	if (lnRefList->length <= 0) {
		return IEC61850_ERROR_NO_MEMORY;
	}

	printf("LN Reference List:\n");
	PrintStringList(lnRefList);
	printf("Please select LN ref:\n");
	lnIndex = GetIndexFromUser();


	printf("FC List:\n");
	for (i = 0; i < 13; i++) {
		printf("%d.%s\n", i + 1, FC[i]);
	}
	fcIndex = GetIndexFromUser();

	request.reference = "";
	if (lnIndex >= 1 && lnIndex <= lnRefList->length) {
		request.reference = lnRefList->list[lnIndex - 1];
	}
	request.fc = "XX";
	if (fcIndex >= 1 && fcIndex <= 13) {
		request.fc = FC[fcIndex - 1];
	}
	result = IEC61850_GetAllDataValues(iec61850, serverIndex, &request, &response);
	if (result == S_OK) {
		PrintGetAllDataValuesResponse(&response);
	} else {
		printf("result:[%d]\n", result);
	}
	FreeGetAllDataValues_Response(&response);
	FreeStringList(lnRefList);
	return result;
}

IEC61850_ErrorCode GetAllCBValues()
{
	IEC61850_ErrorCode result = S_OK;
	IEC61850 iec61850 = GetMyServerClient();
	unsigned int serverIndex = 0;
	GetAllCBValues_Request request = { 0 };
	GetAllCBValues_Response response = { 0 };
	enum IEC61850_ACSIClass acsiClass = ACSI_CLASS_RESERVED;
	int loopCount = 0;
	unsigned int lnIndex = 0;

	struct StringList* lnList = StringListMalloc();

	StringListAdd(lnList, "ServerIEDExample/LLN0");
	StringListAdd(lnList, "ServerIEDExample/CSWI0");
	StringListAdd(lnList, "ServerIEDExample/GGIO0");
	StringListAdd(lnList, "ServerIEDExample/MMXU0");
	StringListAdd(lnList, "ServerIEDExample/PDIF0");
	StringListAdd(lnList, "ServerIEDExample/IARC0");

	if (lnList->length <= 0) {
		return IEC61850_ERROR_NO_MEMORY;
	}

	printf("Logical Node List:\n");
	PrintStringList(lnList);
	printf("Please select LN ref:\n");

	lnIndex = GetIndexFromUser();

	do {
		loopCount = loopCount % 3;
		if (loopCount == 0) {
			printf("Please select the ACSIClass from:\n");
			printf("  3. BRCB\n");
			printf("  4. URCB\n");
			printf("  5. LCB\n");
			printf("  7. SGCB\n");
			printf("  8. GoCB\n");
			printf(" 10. MSVCB\n");
		}
		acsiClass = (enum IEC61850_ACSIClass)GetIndexFromUser();
		printf("\n");
		loopCount++;
	} while (acsiClass != 3 && acsiClass != 4 && acsiClass != 5 && acsiClass != 7 && acsiClass != 8 && acsiClass != 10);

	request.reference = "";
	if (lnIndex >= 1 && lnIndex <= lnList->length) {
		request.reference = lnList->list[lnIndex - 1];
	}
	request.acsiClass = acsiClass;
	result = IEC61850_GetAllCBValues(iec61850, serverIndex, &request, &response);
	if (result == S_OK) {
		PrintGetAllCBValuesResponse(&response);
	} else {
		printf("result:[%d]\n", result);
	}
	FreeAllCBValues(&response.cbValue);
	FreeStringList(lnList);
	return result;
}

IEC61850_ErrorCode GetDataValues()
{
	IEC61850_ErrorCode result = S_OK;
	IEC61850 iec61850 = GetMyServerClient();
	unsigned int serverIndex = 0;
	struct GetDataValues_Request request = { 0 };
	struct GetDataValues_Response response = { 0 };

	request.dataNum = 2;
	request.FCDAs = calloc(request.dataNum, sizeof(FCDA));
	if (request.FCDAs) {
		strncpy(request.FCDAs[0].reference, "ServerIEDExample/MMXU0.A", OBJECT_REFERENCE_STRING_LEN);
		strncpy(request.FCDAs[0].fc, "MX", FC_LEN);
		strncpy(request.FCDAs[1].reference, "ServerIEDExample/GGIO0.NumSubIntv.minVal", OBJECT_REFERENCE_STRING_LEN);
		strncpy(request.FCDAs[1].fc, "CF", FC_LEN);

		result = IEC61850_GetDataValues(iec61850, serverIndex, &request, &response);
		if (result == S_OK) {
			PrintGetDataValuesResponse(&response);
		} else {
			printf("result:[%d]\n", result);
		}
		FreeGetDataValues_Response(&response);

		free(request.FCDAs);
		request.FCDAs = NULL;
	}

	return result;
}

IEC61850_ErrorCode SetDataValues()
{
	IEC61850_ErrorCode result = S_OK;
	IEC61850 iec61850 = GetMyServerClient();
	unsigned int serverIndex = 0;
	SetDataValues_Request request = { 0 };
	SetDataValues_Response response = { 0 };
	char* ref = "ServerIEDExample/GGIO0.NumSubIntv.minVal";
	S32 newVal = 0;

	request.dataNum = 1;
	request.fcdaVals = calloc(1, sizeof(FCDAVals));
	if (request.fcdaVals == NULL) {
		return IEC61850_ERROR_NO_MEMORY;
	}

	printf("Will set data: [%s]\nPlease input new data value:\n", ref);
	newVal = GetInteger32FromUser();

	strncpy(request.fcdaVals->dataRef, ref, OBJECT_REFERENCE_STRING_LEN);
	strncpy(request.fcdaVals->FC, "CF", FC_LEN);
	request.fcdaVals->dataAttribute.type = IEC61850_DATATYPE_INT32;
	request.fcdaVals->dataAttribute.bitLength = 32;
	request.fcdaVals->dataAttribute.pvData = &newVal;

	result = IEC61850_SetDataValues(iec61850, serverIndex, &request, &response);
	if (result == S_OK) {
		unsigned int i = 0;
		printf("request:\n");
		for (i = 0; i < request.dataNum; i++) {
			printf("data[%u]:\n  reference: [%s]\n  fc: [%s]\n  value:\n", i + 1, request.fcdaVals[i].dataRef, request.fcdaVals[i].FC);
			PrintDataValue(&request.fcdaVals->dataAttribute, 2, FALSE);
		}
		printf("response:\n");
		PrintSetDataValuesResponse(&response);
	} else {
		printf("result:[%d]\n", result);
	}
	FreeSetDataValues_Response(&response);

	free(request.fcdaVals);
	request.fcdaVals = NULL;

	return result;
}

IEC61850_ErrorCode GetDataDirectory()
{
	IEC61850_ErrorCode result = S_OK;
	IEC61850 iec61850 = GetMyServerClient();
	unsigned int serverIndex = 0;
	GetDataDirectory_Request request = { 0 };
	GetDataDirectory_Response response = { 0 };
	unsigned int dataIndex = 0;
	struct StringList* dataRefList = StringListMalloc();

	StringListAdd(dataRefList, "ServerIEDExample/LLN0.Mod");
	StringListAdd(dataRefList, "ServerIEDExample/MMXU0.A");
	StringListAdd(dataRefList, "ServerIEDExample/CSWI0.Pos");
	StringListAdd(dataRefList, "ServerIEDExample/PDIF0.TmASt");
	StringListAdd(dataRefList, "P_L2201APLD0/LLN0.Mod");
	StringListAdd(dataRefList, "P_L2201APPROT/FOCH1PSCH1.ProTx");
	if (dataRefList->length <= 0) {
		return S_OK;
	}

	printf("Data Ref List:\n");
	PrintStringList(dataRefList);
	printf("Please select data ref:\n");

	dataIndex = GetIndexFromUser();

	request.dataReference = "";
	if (dataIndex >= 1 && dataIndex <= dataRefList->length) {
		request.dataReference = dataRefList->list[dataIndex - 1];
	}
	request.referenceAfter = NULL;
	result = IEC61850_GetDataDirectory(iec61850, serverIndex, &request, &response);
	if (result == S_OK) {
		PrintGetDataDirectoryResponse(&response);
	} else {
		printf("result:[%d]\n", result);
	}
	FreeStringList(dataRefList);
	FreeGetDataDirectory_Response(&response);
	return result;
}

IEC61850_ErrorCode GetDataDefinition()
{
	IEC61850_ErrorCode result = S_OK;
	IEC61850 iec61850 = GetMyServerClient();
	unsigned int serverIndex = 0;
	GetDataDefinition_Request request = { 0 };
	GetDataDefinition_Response response = { 0 };
	unsigned int dataIndex = 0;
	unsigned int fcIndex = 0;
	char FC[13][3] = { "ST","MX","SP","SV","CF","DC","SG","SE","SR","OR","BL","EX","XX" };
	struct StringList* dataRefList = StringListMalloc();

	StringListAdd(dataRefList, "ServerIEDExample/MMXU0.A");
	StringListAdd(dataRefList, "ServerIEDExample/PDIF0.TmASt");
	StringListAdd(dataRefList, "ServerIEDExample/QFVR0.VarStr");
	StringListAdd(dataRefList, "ServerIEDExample/NHAS.nohas");
	if (dataRefList->length <= 0) {
		return IEC61850_ERROR_NO_MEMORY;
	}

	printf("Data Ref List:\n");
	PrintStringList(dataRefList);
	printf("Please select data reference:\n");
	dataIndex = GetIndexFromUser();

	if (dataIndex >= 1 && dataIndex <= dataRefList->length) {
		strncpy(request.reference, dataRefList->list[dataIndex - 1], OBJECT_REFERENCE_STRING_LEN);
	}

	while (fcIndex == 0 || fcIndex > 13) {
		printf("FC List:\n");
		for (fcIndex = 0; fcIndex < 13; fcIndex++) {
			printf("%d.%s\n", fcIndex + 1, FC[fcIndex]);
		}

		fcIndex = GetIndexFromUser();
	}

	strncpy(request.fc, FC[fcIndex - 1], FC_LEN);

	result = IEC61850_GetDataDefinition(iec61850, serverIndex, &request, &response);
	if (result == S_OK) {
		PrintGetDataDefinitionResponse(&response);
	} else {
		printf("result:[%d]\n", result);
	}

	FreeGetDataDefinition_Response(&response);
	FreeStringList(dataRefList);

	return result;
}

IEC61850_ErrorCode CreateDataSet()
{
	IEC61850_ErrorCode result = S_OK;
	IEC61850 iec61850 = GetMyServerClient();
	unsigned int serverIndex = 0;
	CreateDataSet_Request request = { 0 };
	int serviceError = SERVICE_ERROR_NO_ERROR;
	FCDA fcdaList[2] = { 0 };
	unsigned int i = 0;

	request.datasetReference = "ServerIEDExample/LLN0.PersistentDS";
	request.fcdaList = fcdaList;
	request.dataNum = 2;

	strncpy(fcdaList[0].reference, "ServerIEDExample/LLN0.Beh.stVal", OBJECT_REFERENCE_STRING_LEN);
	strncpy(fcdaList[1].reference, "ServerIEDExample/LPHD0.Beh.stVal", OBJECT_REFERENCE_STRING_LEN);
	strncpy(fcdaList[0].fc, "ST", FC_LEN);
	strncpy(fcdaList[1].fc, "ST", FC_LEN);

	result = IEC61850_CreateDataSet(iec61850, serverIndex, &request, &serviceError);
	if (result == S_OK) {
		printf("request:\n  datasetReference: [%s]\n", request.datasetReference);

		for (i = 0; i < request.dataNum; i++) {
			printf("  memberData[%d]:\n    reference: [%s]\n    fc: [%s]\n", i + 1, request.fcdaList[i].reference, request.fcdaList[i].fc);
		}
		printf("\n");
		if (serviceError == SERVICE_ERROR_NO_ERROR) {
			printf("response:\nResponse+\n");
		} else {
			printf("response:\nResponse-\n  ServiceError: (%d) %s\n", serviceError, TranslateServiceError(serviceError));
		}
	} else {
		printf("result:[%d]\n", result);
	}

	return result;
}

IEC61850_ErrorCode DeleteDataSet()
{
	IEC61850_ErrorCode result = S_OK;
	IEC61850 iec61850 = GetMyServerClient();
	unsigned int serverIndex = 0;
	int serviceError = SERVICE_ERROR_NO_ERROR;
	char* datasetReference = "ServerIEDExample/LLN0.PersistentDS";

	result = IEC61850_DeleteDataSet(iec61850, serverIndex, datasetReference, &serviceError);
	if (result == S_OK) {
		printf("request:\n  datasetReference: [%s]\n\n", datasetReference);
		if (serviceError == SERVICE_ERROR_NO_ERROR) {
			printf("response:\nResponse+\n");
		} else {
			printf("response:\nResponse-\n  ServiceError: (%d) %s\n", serviceError, TranslateServiceError(serviceError));
		}
	} else {
		printf("result:[%d]\n", result);
	}

	return result;
}

IEC61850_ErrorCode GetDataSetDirectory()
{
	IEC61850_ErrorCode result = S_OK;
	IEC61850 iec61850 = GetMyServerClient();
	unsigned int serverIndex = 0;
	char* datasetReference = "ServerIEDExample/LLN0.svDs";
	GetDataSetDirectory_Response response = { 0 };
	U32 count = 0;

	result = IEC61850_GetDataSetDirectory(iec61850, serverIndex, datasetReference, &response);
	if (result == S_OK && response.FCDAs) {
		for (count = 0; count < response.dataNum; count++) {
			printf("\t%u.%s[%s]\n", count + 1, response.FCDAs[count].reference, response.FCDAs[count].fc);
		}
	}

	FreeGetDataSetDirectory_Response(&response);

	return result;
}

IEC61850_ErrorCode GetDataSetValues()
{
	IEC61850_ErrorCode result = S_OK;
	IEC61850 iec61850 = GetMyServerClient();
	unsigned int serverIndex = 0;
	char* reference = NULL;
	GetDataSetValues_Response response = { 0 };
	unsigned int dataIndex = 0;
	struct StringList* dataRefList = StringListMalloc();
	StringListAdd(dataRefList, "ServerIEDExample/LLN0.logDS");
	StringListAdd(dataRefList, "ServerIEDExample/LLN0.GooseDS");
	StringListAdd(dataRefList, "ServerIEDExample/GGIO0.UnbufferedDS");
	StringListAdd(dataRefList, "ServerIEDExample/LLN0.PersistentDS");

	if (dataRefList->length <= 0) {
		return IEC61850_ERROR_NO_MEMORY;
	}

	printf("Dataset Ref List:\n");
	PrintStringList(dataRefList);
	printf("Please select dataset ref:\n");
	dataIndex = GetIndexFromUser();

	if (dataIndex >= 1 && dataIndex <= dataRefList->length) {
		reference = dataRefList->list[dataIndex - 1];
	}

	result = IEC61850_GetDataSetValues(iec61850, serverIndex, reference, &response);

	if (result == S_OK) {
		PrintGetDataSetValuesResponse(&response);
	} else {
		printf("result:[%d]\n", result);
	}

	FreeGetDataSetValues_Response(&response);
	FreeStringList(dataRefList);

	return result;
}

IEC61850_ErrorCode SetDataSetValues()
{
	IEC61850_ErrorCode result = S_OK;
	IEC61850 iec61850 = GetMyServerClient();
	unsigned int serverIndex = 0;
	SetDataSetValues_Request request = { 0 };
	SetDataSetValues_Response response = { 0 };
	char dbpos = IEC61850_DB_POS_TRUE;
	IEC61850_TimeStamp t = { 0 };
	unsigned int i = 0;

	request.datasetReference = "ServerIEDExample/CSWI0.BufferedDS";
	request.referenceAfter = NULL;
	request.value.dataNum = 2;
	request.value.dataAttributes = calloc(2, sizeof(IEC61850_DataAttributeData));

	if (request.value.dataAttributes) {
		request.value.dataAttributes[0].bitLength = 2;
		request.value.dataAttributes[0].type = IEC61850_DATATYPE_CODED_ENUM;
		request.value.dataAttributes[0].pvData = &dbpos;

		IEC61850_GetTime(NULL, &t);
		request.value.dataAttributes[1].bitLength = IEC61850_TIMESTAMP_BITSIZE;
		request.value.dataAttributes[1].type = IEC61850_DATATYPE_TIMESTAMP;
		request.value.dataAttributes[1].pvData = &t;

		result = IEC61850_SetDataSetValues(iec61850, serverIndex, &request, &response);
		if (result == S_OK) {
			printf("request:\n  datasetReference: [%s]\n", request.datasetReference);
			if (request.referenceAfter) {
				printf("  referenceAfter: [%s]\n", request.referenceAfter);
			}
			for (i = 0; i < request.value.dataNum; i++) {
				printf("  memberValue[%d]:\n", i + 1);
				PrintDataValue(&(request.value.dataAttributes[i]), 2, FALSE);
			}
			PrintSetDataSetValuesResponse(&response);
		} else {
			printf("result:[%d]\n", result);
		}

		FreeSetDataSetValues_Response(&response);
		free(request.value.dataAttributes);
		request.value.dataAttributes = NULL;
	} else {
		return IEC61850_ERROR_NO_MEMORY;
	}

	return result;
}

IEC61850_ErrorCode GetBufferedReportControlBlockValues()
{
	IEC61850_ErrorCode result = S_OK;
	IEC61850 iec61850 = GetMyServerClient();
	unsigned int serverIndex = 0;

	char* reference = "ServerIEDExample/CSWI0.BufferedCB01";
	GetBRCBValues_Response response = { 0 };

	result = IEC61850_GetBRCBValues(iec61850, serverIndex, reference, &response);
	if (result == S_OK) {
		printf("request:\n\tbrcb reference: %s\n", reference);

		printf("response:\n");
		PrintGetBRCBValuesResponse(&response);
	}

	return result;
}

IEC61850_ErrorCode SetBufferedReportControlBlockValues()
{
	IEC61850_ErrorCode result = S_OK;
	IEC61850 iec61850 = GetMyServerClient();
	unsigned int serverIndex = 0;
	SetBRCBValues_Request request = { 0 };
	SetBRCBValues_Response response = { 0 };

	request.numOfRptCB = response.numOfRptCB = 1;
	request.brcbValsList = (tSetBRCBValues*)calloc(request.numOfRptCB, sizeof(tSetBRCBValues));
	if (request.brcbValsList) {
		Boolean rptEna = TRUE;
		request.brcbValsList[0].reference = "ServerIEDExample/CSWI0.BufferedCB01";
		request.brcbValsList[0].rptEna = &rptEna;
		printf("Will set [rptEna] for \"ServerIEDExample/CSWI0.BufferedCB01\"\n");
		rptEna = GetBooleanFromUser();

		result = IEC61850_SetBRCBValues(iec61850, serverIndex, &request, &response);
		if (result == S_OK) {
			PrintSetBRCBValuesResponse(&response);
		} else {
			printf("result:[%d]\n", result);
		}
	} else {
		result = IEC61850_ERROR_NO_MEMORY;
	}

	FreeSetBRCBValues_Response(&response);
	if (request.brcbValsList) {
		free(request.brcbValsList);
	}

	return result;
}

IEC61850_ErrorCode GetUnbufferedReportControlBlockValues()
{
	IEC61850_ErrorCode result = S_OK;
	IEC61850 iec61850 = GetMyServerClient();
	unsigned int serverIndex = 0;

	char* reference = "ServerIEDExample/GGIO0.UnbufferedCB01";
	GetURCBValues_Response response = { 0 };

	result = IEC61850_GetURCBValues(iec61850, serverIndex, reference, &response);
	if (result == S_OK) {
		printf("request urcb reference: %s\n", reference);
		printf("response:\n");
		PrintGetURCBValuesResponse(&response);
	}

	return result;
}

IEC61850_ErrorCode SetUnbufferedReportControlBlockValues()
{
	IEC61850_ErrorCode result = S_OK;
	IEC61850 iec61850 = GetMyServerClient();
	unsigned int serverIndex = 0;
	SetURCBValues_Request request = { 0 };
	SetURCBValues_Response response = { 0 };

	request.numOfRptCB = response.numOfRptCB = 1;
	request.urcbValsList = (tSetURCBValues*)calloc(request.numOfRptCB, sizeof(tSetURCBValues));
	if (request.urcbValsList) {
		Boolean rptEna = TRUE;
		request.urcbValsList[0].reference = "ServerIEDExample/GGIO0.UnbufferedCB01";
		request.urcbValsList[0].rptEna = &rptEna;
		printf("Will set [rptEna] for \"ServerIEDExample/GGIO0.UnbufferedCB01\"\n");
		rptEna = GetBooleanFromUser();

		result = IEC61850_SetURCBValues(iec61850, serverIndex, &request, &response);
		if (result == S_OK) {
			PrintSetURCBValuesResponse(&response);
		} else {
			printf("result:[%d]\n", result);
		}
	} else {
		result = IEC61850_ERROR_NO_MEMORY;
	}

	FreeSetURCBValues_Response(&response);
	if (request.urcbValsList) {
		free(request.urcbValsList);
	}

	return result;
}

IEC61850_ErrorCode QueryLogByTime()
{
	IEC61850_ErrorCode result = S_OK;

	IEC61850_TimeStamp* startTime = NULL;
	IEC61850_TimeStamp* stopTime = NULL;
	IEC61850_LogEntries returnedLogEntries = { 0 };
	char* logRef = "ServerIEDExample/LLN0.logName";

	printf("Please specify the startTime (YYYYMMDDhhmmss): ");
	startTime = GetIEC61850TimeFromUser();

	printf("Please specify the stopTime (YYYYMMDDhhmmss): ");
	stopTime = GetIEC61850TimeFromUser();

	result = IEC61850_QueryLogByTime(GetMyServerClient(), 0, logRef, startTime, stopTime, &returnedLogEntries);
	if (result == S_OK) {
		PrintLogVals(&returnedLogEntries);
	} else {
		printf("result:[%d]\n", result);
	}

	IEC61850_FreeLogEntries(&returnedLogEntries);

	if (startTime) {
		free(startTime);
		startTime = NULL;
	}
	if (stopTime) {
		free(stopTime);
		stopTime = NULL;
	}

	return result;
}

IEC61850_ErrorCode QueryLogAfter()
{
	IEC61850_ErrorCode result = S_OK;
	IEC61850_TimeStamp* startTime = NULL;
	IEC61850_LogEntries returnedLogEntries = { 0 };
	U32 entryId = 0;

	char* logRef = "ServerIEDExample/LLN0.logName";

	printf("Please specify the startTime (YYYYMMDDhhmmss): ");
	startTime = GetIEC61850TimeFromUser();

	printf("Please specify the entryID: ");
#ifdef __PARADIGM__
	scanf("%ld", &entryId);
#else
	scanf("%d", &entryId);
#endif

	result = IEC61850_QueryLogAfter(GetMyServerClient(), 0, logRef, startTime, entryId, &returnedLogEntries);
	if (result == S_OK) {
		PrintLogVals(&returnedLogEntries);
	} else {
		printf("result:[%d]\n", result);
	}

	IEC61850_FreeLogEntries(&returnedLogEntries);

	if (startTime) {
		free(startTime);
		startTime = NULL;
	}

	return result;
}

IEC61850_ErrorCode GetLogStatusValues()
{
	IEC61850_ErrorCode result = S_OK;

	char* domain = "ServerIEDExample";
	char* item = "LLN0$LG$logCBName";
	IEC61850_LogStatus logStatus = { 0 };

	result = IEC61850_GetLogStatusValues(GetMyServerClient(), 0, domain, item, &logStatus);
	if (result == S_OK) {
		PrintLogStatus(&logStatus);
	} else {
		printf("result:[%d]\n", result);
	}

	return result;
}

IEC61850_ErrorCode SelectActiveSG()
{
	IEC61850_ErrorCode result = S_OK;
	IEC61850 iec61850 = GetMyServerClient();
	unsigned int serverIndex = 0;
	char userInput[256] = { 0 };
	eServiceError serviceError = SERVICE_ERROR_NO_ERROR;
	SelectActiveSG_Request request = { 0 };
	request.sgcbReference = "ServerIEDExample/LLN0.SGCB";
	setbuf(stdin, NULL);
	while (request.settingGroupNumber > 5 || request.settingGroupNumber < 1) {
		memset(userInput, 0, 256);
		printf("please input settinggroup active ID[1-5]:");
		if (fgets(userInput, sizeof(userInput), stdin) != NULL) {
			request.settingGroupNumber = atoi(userInput);
		}
	}
	result = IEC61850_SelectActiveSG(iec61850, serverIndex, &request, &serviceError);

	PrintServiceError(serviceError);
	printf("\n");

	return result;
}

IEC61850_ErrorCode SelectEditSG()
{
	IEC61850_ErrorCode result = S_OK;
	IEC61850 iec61850 = GetMyServerClient();
	unsigned int serverIndex = 0;
	char userInput[256] = { 0 };
	eServiceError serviceError = SERVICE_ERROR_NO_ERROR;
	SelectEditSG_Request request = { 0 };
	request.sgcbReference = "ServerIEDExample/LLN0.SGCB";
	while (request.settingGroupNumber > 5 || request.settingGroupNumber < 1) {
		memset(userInput, 0, 256);
		setbuf(stdin, NULL);
		printf("please input settinggroup edit ID[1-5]:");
		if (fgets(userInput, sizeof(userInput), stdin) != NULL) {
			request.settingGroupNumber = atoi(userInput);
		}
	}
	result = IEC61850_SelectEditSG(iec61850, serverIndex, &request, &serviceError);

	PrintServiceError(serviceError);
	printf("\n");

	return result;
}

IEC61850_ErrorCode SetEditSGValue()
{
	IEC61850_ErrorCode result = S_OK;
	IEC61850 iec61850 = GetMyServerClient();
	unsigned int serverIndex = 0;

	SetEditSGValue_Request request = { 0 };
	SetEditSGValue_Response response = { 0 };

	unsigned int index = 0;
	DataRefValue dataRefValue[3] = { 0 };
	eServiceError serviceError[3] = { 0 };
	S32 newVal[3] = { 0 };
	char userInput[16] = { 0 };

	request.dataNum = response.result.errNum = 3;
	
	dataRefValue[0].dataRef = "ServerIEDExample/IARC0.MaxNumRcd.setVal";
	dataRefValue[1].dataRef = "ServerIEDExample/IARC0.OpMod.setVal";
	dataRefValue[2].dataRef = "ServerIEDExample/IARC0.MemFull.setVal";

	request.dataRefValues = dataRefValue;
	response.result.serviceErrs = serviceError;
	for (index = 0; index < request.dataNum; index++) {
		printf("please input new value for [%s]: ", dataRefValue[index].dataRef);
		memset(userInput, 0, 16);
		setbuf(stdin, NULL);
		if (fgets(userInput, sizeof(userInput), stdin) != NULL) {
			newVal[index] = atoi(userInput);
		}
		dataRefValue[index].dataAttribute.type = IEC61850_DATATYPE_INT32;
		dataRefValue[index].dataAttribute.bitLength = 32;
		dataRefValue[index].dataAttribute.pvData = &newVal[index];
	}

	result = IEC61850_SetEditSGValue(iec61850, serverIndex, &request, &response);

	for (index = 0; index < request.dataNum; index++) {
		printf("set [%s] result: [%s (%d)]\n", dataRefValue[index].dataRef, TranslateServiceError(response.result.serviceErrs[index]), response.result.serviceErrs[index]);
	}
	printf("\n");

	return result;
}

IEC61850_ErrorCode ConfirmEditSGValues()
{
	IEC61850_ErrorCode result = S_OK;
	IEC61850 iec61850 = GetMyServerClient();
	unsigned int serverIndex = 0;

	char* sgcbReference = "ServerIEDExample/LLN0.SGCB";
	eServiceError serviceError = SERVICE_ERROR_NO_ERROR;

	result = IEC61850_ConfirmEditSGValues(iec61850, serverIndex, sgcbReference, &serviceError);

	PrintServiceError(serviceError);
	printf("\n");

	return result;
}

IEC61850_ErrorCode GetEditSGValue()
{
	IEC61850_ErrorCode result = S_OK;
	IEC61850 iec61850 = GetMyServerClient();
	unsigned int serverIndex = 0;

	char* itemNameMaxNumRcd = "ServerIEDExample/IARC0.MaxNumRcd.setVal";
	char* itemNameOpMod = "ServerIEDExample/IARC0.OpMod.setVal";
	char* itemNameMemFull = "ServerIEDExample/IARC0.MemFull.setVal";

	S32 newValMaxNumRcd = 0, newValOpMod = 0, newValMemFull = 0;

	GetEditSGValue_Request request = { 0 };
	GetEditSGValue_Response response = { 0 };
	IEC61850_DataAttributeData da[3] = { 0 };
	FCDA fcda[3] = { 0 };
	char userInput[16] = { 0 };

	request.numOfFCDA = 3;

	request.FCDAs = fcda;
	strncpy(fcda[0].reference, itemNameMaxNumRcd, OBJECT_REFERENCE_STRING_LEN);
	strncpy(fcda[1].reference, itemNameOpMod, OBJECT_REFERENCE_STRING_LEN);
	strncpy(fcda[2].reference, itemNameMemFull, OBJECT_REFERENCE_STRING_LEN);

	printf("please select FC:\n1)SG \n2)SE\n:");
	setbuf(stdin, NULL);
	if (fgets(userInput, sizeof(userInput), stdin) != NULL) {
		switch (userInput[0]) {
		case '1': {
			strncpy(fcda[0].fc, "SG", FC_LEN);
			strncpy(fcda[1].fc, "SG", FC_LEN);
			strncpy(fcda[2].fc, "SG", FC_LEN);
			break;
		}
		case '2': {
			strncpy(fcda[0].fc, "SE", FC_LEN);
			strncpy(fcda[1].fc, "SE", FC_LEN);
			strncpy(fcda[2].fc, "SE", FC_LEN);
			break;
		}
		default:
			break;
		}
	}

	response.value.dataAttributes = da;
	da[0].pvData = &newValMaxNumRcd;
	da[1].pvData = &newValOpMod;
	da[2].pvData = &newValMemFull;
	da[0].bitLength = 32;
	da[1].bitLength = 32;
	da[2].bitLength = 32;

	result = IEC61850_GetEditSGValue(iec61850, serverIndex, &request, &response);

	if (result == S_OK) {
		SetMaxNumRcd(newValMaxNumRcd);
		SetOpMod(newValOpMod);
		SetMemFull(newValMemFull);
		printf("MaxNumRcd=%d, OpMod=%d, MemFull=%d\n", newValMaxNumRcd, newValOpMod, newValMemFull);
	} else {
		printf("result:[%d]\n", result);
	}

	PrintServiceError(response.serviceError);
	printf("\n");

	return result;
}

IEC61850_ErrorCode GetSGCBValues()
{
	IEC61850_ErrorCode result = S_OK;

	GetSGCBValues_Response response = { 0 };
	char* sgcbReference = "ServerIEDExample/LLN0.SGCB";

	IEC61850_GetSGCBValues(GetMyServerClient(), 0, sgcbReference, &response);

	if (result == S_OK) {
		IEC61850_DateTime dateTime = { 0 };
		IEC61850_GetDateFromIEC61850Time(&dateTime, &response.sgcbValues.lActTm);

		printf("SGCB Values:\n");
		printf("\tnumOfSG: [%d]\n", response.sgcbValues.numOfSG);
		printf("\tactSG:   [%d]\n", response.sgcbValues.actSG);
		printf("\teditSG:  [%d]\n", response.sgcbValues.editSG);
		printf("\tlActTm:  [%02u/%02u/%u %02u:%02u:%02u]\n", dateTime.month, dateTime.tm_mday, dateTime.year, dateTime.tm_hour, dateTime.tm_min, dateTime.tm_sec);
		printf("\tresvTms: [%d]\n", response.sgcbValues.resvTms);
	}

	PrintServiceError(response.serviceError);
	printf("\n");

	return result;
}

IEC61850_ErrorCode MMSGetFile()
{
	IEC61850_ErrorCode result = S_OK;
	IEC61850 iec61850 = GetMyServerClient();
	unsigned int serverIndex = 0;

	char remoteFileName[256] = { 0 };
	char localFileName[256] = { 0 };

	GetFileNameFromUser("Enter the remote source file name: ", remoteFileName);
	GetFileNameFromUser("Enter the local destination file name: ", localFileName);

	result = IEC61850_GetFile(iec61850, serverIndex, remoteFileName, localFileName);
	if (result == S_OK) {
		/* Set the Error String to NONE */
		char strError[SIZE_OF_ERROR_STRING] = { 0 };
		snprintf(strError, SIZE_OF_ERROR_STRING, "Get File success.");
		SetErrorString(strError, SIZE_OF_ERROR_STRING);
	}

	return result;
}

IEC61850_ErrorCode MMSSetFile()
{
	IEC61850_ErrorCode result = S_OK;
	IEC61850 iec61850 = GetMyServerClient();
	unsigned int serverIndex = 0;
	char remoteFileName[256] = { 0 };
	char localFileName[256] = { 0 };

	GetFileNameFromUser("Enter the local source file name: ", localFileName);
	GetFileNameFromUser("Enter the remote destination file name: ", remoteFileName);
	result = IEC61850_SetFile(iec61850, serverIndex, remoteFileName, localFileName);
	if (result == S_OK) {
		/* Set the Error String to NONE */
		char strError[SIZE_OF_ERROR_STRING] = { 0 };
		snprintf(strError, SIZE_OF_ERROR_STRING, "Set File success.");
		SetErrorString(strError, SIZE_OF_ERROR_STRING);
	}

	return result;
}

IEC61850_ErrorCode MMSDeleteFile()
{
	IEC61850_ErrorCode result = S_OK;
	IEC61850 iec61850 = GetMyServerClient();
	unsigned int serverIndex = 0;
	char remoteFileName[256] = { 0 };
	Boolean cont = FALSE;
	char userInput[256] = { 0 }; //Buffer to hold the user input

	GetFileNameFromUser("Enter the file name for deletion: ", remoteFileName);

	printf("WARNING: this will permanently delete the file \"%s\" - Do you want to continue? type Y or y: ", remoteFileName);

	if (fgets(userInput, sizeof(userInput), stdin) != NULL) {
		switch (userInput[0]) //Base the return val on the input
		{
		case 'y':
		case 'Y':
			cont = TRUE;
			break;
		default:
			cont = FALSE;
			break;
		}
	}

	if (cont == TRUE) {
		/* send delete file command */
		result = IEC61850_DeleteFile(iec61850, serverIndex, remoteFileName);
		if (result == S_OK) {
			/* Set the Error String to NONE */
			char strError[SIZE_OF_ERROR_STRING] = { 0 };
			snprintf(strError, SIZE_OF_ERROR_STRING, "Delete File success.");
			SetErrorString(strError, SIZE_OF_ERROR_STRING);
		}
	}

	if (result != S_OK) {
		/* If the function failed alert the user */
		char strError[SIZE_OF_ERROR_STRING] = { 0 };
		snprintf(strError, SIZE_OF_ERROR_STRING, "Delete File failed: %i: %s\n", result, IEC61850_ErrorString(result) == NULL ? "Error" : IEC61850_ErrorString(result));
		SetErrorString(strError, SIZE_OF_ERROR_STRING);
	}
	return result;
}

IEC61850_ErrorCode MMSGetFileAttributeValues()
{
	IEC61850_ErrorCode result = S_OK;
	tFileAttr fileAttributes = { 0 }; //tFileAttr to hold the returned attributes
	char fileName[IEC61850_FILENAME_SIZE] = { 0 };
	IEC61850 iec61850 = GetMyServerClient();
	unsigned int fileCount = 0; //file count
	unsigned int serverIndex = 0; //selected server index

	/* prompt for file or directory */
	GetFileNameFromUser("Enter a file name or directory (leave blank to get current directory): ", fileName);

	/* request the attributes */
	result = IEC61850_GetFileAttributeValues(iec61850, serverIndex, fileName, NULL, &fileAttributes);
	if (result == S_OK) {
		/* Set the Error String to NONE */
		char strError[SIZE_OF_ERROR_STRING] = { 0 };
		snprintf(strError, SIZE_OF_ERROR_STRING, "GetFileAttributeValues success.");
		SetErrorString(strError, SIZE_OF_ERROR_STRING);

		/* Print list of files and attributes */
		printf("\n\n\tReceived attributes for %d file(s):\n", fileAttributes.numOfDirectoryEntries);
		printf("\tFile\tTimestamp\tSize (bytes)\tFile Name\n");
		for (fileCount = 0; fileCount < fileAttributes.numOfDirectoryEntries; fileCount++) {
			printf("\t%u:\t%s\t%u\t\t%s\n", fileCount + 1, fileAttributes.directoryEntries[fileCount].lastModified, fileAttributes.directoryEntries[fileCount].fileSize, fileAttributes.directoryEntries[fileCount].fileName);
		}
		printf("\n");
	} else {
		/* If the function failed alert the user */
		char strError[SIZE_OF_ERROR_STRING] = { 0 };
		snprintf(strError, SIZE_OF_ERROR_STRING, "GetFileAttributeValues failed: %i: %s\n", result, IEC61850_ErrorString(result) == NULL ? "Error" : IEC61850_ErrorString(result));
		SetErrorString(strError, SIZE_OF_ERROR_STRING);
	}

	IEC61850_DestroyFileAttributeValues(&fileAttributes);
	return result;
}

IEC61850_ErrorCode MMS_Read()
{
	IEC61850_ErrorCode result = S_OK;
	IEC61850 iec61850 = GetMyServerClient();

	FCDA dataRefFC[3] = { 0 };
	IEC61850_DataAttributeData datasToBeRead[3] = { 0 };
	eServiceError serviceErr[3] = { 0 };

	strncpy(dataRefFC[0].reference, "ServerIEDExample/MMXU0.A.phsC", OBJECT_REFERENCE_STRING_LEN);
	strncpy(dataRefFC[0].fc, "MX", FC_LEN);
	strncpy(dataRefFC[1].reference, "ServerIEDExample/MMXU0.A.phsA", OBJECT_REFERENCE_STRING_LEN);
	strncpy(dataRefFC[1].fc, "MX", FC_LEN);
	strncpy(dataRefFC[2].reference, "ServerIEDExample/MMXU0.A.phsB.cVal.mag.i", OBJECT_REFERENCE_STRING_LEN);
	strncpy(dataRefFC[2].fc, "MX", FC_LEN);

	result = IEC61850_ReadDirect(iec61850, 0, dataRefFC, datasToBeRead, serviceErr, 3);

	if (result == S_OK) {
		unsigned int index = 0;
		for (index = 0; index < 3; index++) {
			printf("No.%u:%s[%s]:\n", index + 1, dataRefFC[index].reference, dataRefFC[index].fc);
			PrintServiceError(serviceErr[index]);
			if (serviceErr[index] == SERVICE_ERROR_NO_ERROR) {
				PrintDAVal(&datasToBeRead[index], 2);
			}
		}
	} else {
		printf("Read failed\n");
	}

	FreeDataAttributeDatas(datasToBeRead, 3);
	getchar();
	return result;
}


IEC61850_ErrorCode MMS_Write()
{
	IEC61850_ErrorCode result = S_OK;
	IEC61850 iec61850 = GetMyServerClient();

	static S32 step = 1;
	S32 setVal = 1 + (++step);
	S32 minVal = 2 + step;
	S32 maxVal = 3 + step;

	FCDA dataRefFC[3] = { 0 };
	IEC61850_DataAttributeData datasToBeWrite[3] = { 0 };
	eServiceError serviceErr[3] = { 0 };

	strncpy(dataRefFC[0].reference, "ServerIEDExample/GGIO0.NumSubIntv.setVal", OBJECT_REFERENCE_STRING_LEN);
	strncpy(dataRefFC[0].fc, "SP", FC_LEN);
	strncpy(dataRefFC[1].reference, "ServerIEDExample/GGIO0.NumSubIntv.minVal", OBJECT_REFERENCE_STRING_LEN);
	strncpy(dataRefFC[1].fc, "CF", FC_LEN);
	strncpy(dataRefFC[2].reference, "ServerIEDExample/GGIO0.NumSubIntv.maxVal", OBJECT_REFERENCE_STRING_LEN);
	strncpy(dataRefFC[2].fc, "CF", FC_LEN);

	datasToBeWrite[0].type = IEC61850_DATATYPE_INT32;
	datasToBeWrite[0].bitLength = 32;
	datasToBeWrite[0].pvData = &setVal;

	datasToBeWrite[1].type = IEC61850_DATATYPE_INT32;
	datasToBeWrite[1].bitLength = 32;
	datasToBeWrite[1].pvData = &minVal;

	datasToBeWrite[2].type = IEC61850_DATATYPE_INT32;
	datasToBeWrite[2].bitLength = 32;
	datasToBeWrite[2].pvData = &maxVal;

	result = IEC61850_WriteDirect(iec61850, 0, dataRefFC, datasToBeWrite, serviceErr, 3);

	if (result == S_OK) {
		printf("Write success\n");
	} else {
		printf("Write failed\n");
	}
	getchar();
	return result;
}

IEC61850_ErrorCode Discover(U32 type)
{
	IEC61850_ErrorCode result = S_OK;
	IEC61850 iec61850 = GetMyServerClient();
	FILE* file = NULL;

	StringList* ss = StringListMalloc();
	
	file = fopen("mms-discovery.txt", "w+");
	
	result = IEC61850_GetNamedList(iec61850, 0, NULL, QUERY_LEVEL_SERVER_DIR, ss);
	if (result == S_OK) {
		unsigned int i, j;
		for (i = 0; i < ss->length; i++) {
			StringList* ss_ld = StringListMalloc();
			char* domainName = ss->list[i];
			fprintf(file, "%s\n", domainName);
			result = IEC61850_GetNamedList(iec61850, 0, domainName, QUERY_LEVEL_LD_DIR, ss_ld);
			if (result == S_OK) {
				for (j = 0; j < ss_ld->length; j++) {
					IEC61850_DataTypeInfo dataTypeInfo = { 0 };
					char* ref = ss_ld->list[j];

					//IEC61850_GetVariableAccessAttributes(iec61850, 0, domainName, ref, &dataTypeInfo);
					//fprintf(file, "%s     [type=%d]    [size=%d]\n", ref, dataTypeInfo.type, dataTypeInfo.size);
					//IEC61850_FreeDataTypeInfo(&dataTypeInfo);

					fprintf(file, "%s\n", ref);
				}
			}

			// FreeStringList(ss_ld);
			// ss_ld = StringListMalloc();
			// result = IEC61850_GetNamedList(iec61850, 0, domainName, QUERY_LEVEL_LN_DIR, ss_ld);
			// if (result == S_OK) {
			// 	for (j = 0; j < ss_ld->length; j++) {
			// 		char* ref = ss_ld->list[j];
			// 		fprintf(file, "%s\n", ref);
			// 	}
			// }

			// FreeStringList(ss_ld);
			// ss_ld = StringListMalloc();
			// result = IEC61850_GetNamedList(iec61850, 0, domainName, QUERY_LEVEL_DATASET, ss_ld);
			// if (result == S_OK) {
			// 	for (j = 0; j < ss_ld->length; j++) {
			// 		char* ref = ss_ld->list[j];
			// 		fprintf(file, "%s\n", ref);
			// 	}
			// }

			// FreeStringList(ss_ld);
			// ss_ld = StringListMalloc();
			// result = IEC61850_GetNamedList(iec61850, 0, domainName, QUERY_LEVEL_LOG, ss_ld);
			// if (result == S_OK) {
			// 	for (j = 0; j < ss_ld->length; j++) {
			// 		char* ref = ss_ld->list[j];
			// 		fprintf(file, "%s\n", ref);
			// 	}
			// }

			FreeStringList(ss_ld);
		}
	}
	
	FreeStringList(ss);
	
	fclose(file);

	printf("finished.");

	return result;
}

IEC61850_ErrorCode InnerTestServer()
{
	return S_OK;
}

IEC61850_ErrorCode InnerTestClient()
{
	return S_OK;
}
